﻿/*
	[ru]	Пример работы с ландшафтом.
*/

#include "CTerrain_sm5.h"


//
// Example
//

class CExample : public ICoreEventListener
{
private:
	CTerrainPtr				pTerrain;
	ITerrainEditor			pEditor;
	CRenderQueue			cRQ;
	CInputCameraComp		cCamera;
	CVideoRender			cVideo;
	CAVIVideoEncoder		cEncoder;
	uint					uInputIndex;
	float					fLastTime;
	bool					bIsCameraActive;
	bool					bVideoCreated,
							bVideoEnabled;

public:
	CExample():
		fLastTime(0), bIsCameraActive(true), uInputIndex(0), pEditor(nullptr),
		cVideo( &cEncoder, true ), bVideoCreated(false), bVideoEnabled(false)
	{
	}

	~CExample()
	{
	}

	void Draw();
	void Process();

	virtual void OnInit();
	virtual void OnFree();

	virtual void OnUpdate();

	virtual void Release()									{ delete this; }
	virtual e_win_event::type GetEvents()					{ return e_win_event::UNKNOWN; }

	virtual void ProcessMessage(const TWindowEvent &sEvent)	{}
	virtual void OnException()								{}

	static int s_RunEngine();
};




inline void CExample::Draw()
{
	RENDERGL()->ClearBuffers();
	
	TCameraRenderQueue	*p_crq = nullptr;
	
	// build render queue
	if ( cRQ.GetRenderQueue( &cCamera, p_crq ) )
	{
		const frustum_t *	p_frustum;
		vec3				v_pos;
		vec2				v_clip;

		p_crq->Camera()->GetParameters( nullptr, nullptr, &p_frustum, nullptr, &v_pos, &v_clip, nullptr );
		p_crq->ClearMem();

		pTerrain->Render( p_crq );
	}
	
	RENDER()->GetRenderTech()->Render( &cRQ, uInputIndex );


	//if ( bVideoEnabled )
	//	cVideo.AddFrame();

	RENDERGL()->SwapBuffers();
}


inline void CExample::Process()
{
	INPUT()->Update();

	if ( INPUT()->IsKey(e_key::ESCAPE) )
		CORE()->QuitEngine();
	
	if ( INPUT()->IsMBClick(e_mouse::RIGHT) )
		bIsCameraActive = !bIsCameraActive;

	if ( bIsCameraActive )
	{
		TSNCompMessage	msg;
		msg.Update( nullptr, CORE()->GetUpdateTimeDelta() );

		cCamera.ProcessMessage( msg );
	
		INPUT()->CursorToCenter();
		INPUT()->SetParams( e_input_flags::HIDE_CURSOR | e_input_flags::EXCLUSIVE );
	}
	else
		INPUT()->SetParams( e_input_flags::UNKNOWN );

	
	if ( INPUT()->IsKey( e_key::F1 ) )	uInputIndex = 0;	// default
	if ( INPUT()->IsKey( e_key::F2 ) )	uInputIndex = 1;	// normals
	if ( INPUT()->IsKey( e_key::F3 ) )	uInputIndex = 2;	// depth
	if ( INPUT()->IsKey( e_key::F4 ) )	uInputIndex = 3;	// color
	if ( INPUT()->IsKey( e_key::F5 ) )	uInputIndex = 4;	// light
	if ( INPUT()->IsKey( e_key::F6 ) )	uInputIndex = 5;	// specular
	if ( INPUT()->IsKey( e_key::F7 ) )	uInputIndex = 6;	// shadow map
	if ( INPUT()->IsKey( e_key::F8 ) )	uInputIndex = 7;
	if ( INPUT()->IsKey( e_key::F9 ) )	uInputIndex = 8;
	if ( INPUT()->IsKey( e_key::F10 ) )	uInputIndex = 9;
	if ( INPUT()->IsKey( e_key::F11 ) )	uInputIndex = 10;
	if ( INPUT()->IsKey( e_key::F12 ) )	uInputIndex = 11;


	if ( INPUT()->IsKeyClick( e_key::_9 ) && !bVideoCreated )
	{
		bVideoCreated = cVideo.Create( "..\\video\\v1.avi", urect(uvec2(), RENDER()->GetViewport()->Size()),
										30, e_video_create::AUTO );
	}

	if ( INPUT()->IsKeyClick( e_key::_0 ) && bVideoCreated )
	{
		bVideoCreated = false;
		cVideo.Close();
	}

	if ( INPUT()->IsKeyClick( e_key::V ) )
		bVideoEnabled = !bVideoEnabled;


	if ( INPUT()->IsKeyClick( e_key::RETURN ) )
	{
		RENDERGL()->ScreenShot( "..\\screenshots\\screenshot" );
	}

	INPUT()->Reset();
}


void CExample::OnInit()
{
	bool	ret = true;

	IRenderTechnique	*p_tech = nullptr;

	ret &= RENDER()->GetRTManager()->CreateTechnique( p_tech, e_technique::DEFERRED_SHADING );
	RENDER()->SetRenderTechnique( p_tech );


	RENDERGL()->SetClearColor( color4f(0.3f) );
	RENDERGL()->SetClearDepth( 1.f );

	SMAN()->Enable( e_gl_state::DEPTH_TEST );
	SMAN()->Disable( e_gl_state::CULL_FACE );
	
	
	cCamera.SetType( CInputCameraComp::CT_FPS );
	cCamera.Create( vec3(0.f, -20.f, 0.f), vec3(), vec2(1.f, 12000.f), 0.5f );
	cCamera.SetSens( 0.07f, vec3(1.f), 0.5f, e_vec_swizzle::DEFAULT );


	/*cCamera.SetType( CInputCameraComp::CT_FLIGHT );
	cCamera.Create( vec3(), vec3(), vec2(1.f, 5000.f), 0.5f );
	cCamera.SetSens( 0.07f, vec3(1.f, -2.f, 1.f), 0.1f, e_vec_swizzle::type(0x0012) );*/

	TCameraRenderQueue *	p_crq = new TCameraRenderQueue();

	ret &= p_crq->Create( & cCamera, e_render_layer::ALL_BITS, e_renqueue_flags::UNKNOWN );

	cRQ.AddCamera( p_crq );

	pTerrain = new CTerrain_sm5();
	pTerrain->GetEditor( pEditor );

	ASSERT( ret );
}


void CExample::OnFree()
{
	cVideo.Close();
	cVideo.SetVideoEncoder( nullptr );
}


void CExample::OnUpdate()
{
	CORE()->Update();
	Draw();
	
	fLastTime += CORE()->GetUpdateTimeDelta();

	if ( fLastTime > 1.f/60.f )
	{
		fLastTime = 0.f;
		Process();
	}
}


int CExample::s_RunEngine()
{
	CExample	*		p_example			= new CExample();
	TEngInitParams		s_init_params;
	e_log_output::bits	e_log_bits			= e_log_output::LOG_FILE_BIT
											DEBUG_ONLY( | e_log_output::MESSAGE_BIT )
											;
	
	s_init_params.eFlags					= e_eng_init_flags::OPENGL_4_2
											| e_eng_init_flags::CORE_PROFILE
											| e_eng_init_flags::EXTENDED_CONTEXT
											//| e_eng_init_flags::DEBUG_MODE
											//| e_eng_init_flags::STREAMED_LOAD
											//| e_eng_init_flags::STEREO
											//| e_eng_init_flags::ES2_PROFILE
											;
	s_init_params.sApplicationName			= "Terrain";
	s_init_params.sClassName				= "";
	s_init_params.pHandle					= nullptr;
	s_init_params.pIcon						= nullptr;

	s_init_params.sAudioParams.sAudioDevice	= "";

	s_init_params.sRenInit.uColorDepth		= 32;
	s_init_params.sRenInit.uZBufferDepth	= 24;
	s_init_params.sRenInit.uStencilDepth	= 0;
	s_init_params.sRenInit.uColorSamples	= 0;
	s_init_params.sRenInit.uCSAASamples		= 0;
	s_init_params.sRenInit.uMSAASamples		= 0;
	s_init_params.sRenInit.uPixelFormat		= 0;

	s_init_params.sRenParams.bFullScreen	= false;
	s_init_params.sRenParams.bVSync			= true;
	s_init_params.sRenParams.eMode			= e_window_mode::ALLOW_SIZING | e_window_mode::CENTERED;
	s_init_params.sRenParams.sWinPos		= ivec2( 0, 0 );
	s_init_params.sRenParams.sWinSize		= ivec2( 640, 480 );
	
	s_init_params.sExtParams.uLogLevel		= 15;
	s_init_params.sExtParams.eLogFilter		= e_log_msg::FILTER_ALL;
	s_init_params.sExtParams.eResManFlags	= e_resman_flags::FREE_NON_REF | e_resman_flags::SET_DEFAUL_RES;
	s_init_params.sExtParams.sResDirectory	= "data";
	s_init_params.uLoadThreads				= 0;
	s_init_params.uRenderThreads			= 0;
	
	if ( !RunEngine( p_example, s_init_params, e_log_bits, "log.html", "data\\config\\settings.ocf" ) )
		return 1;

	return 0;
}


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
	return CExample::s_RunEngine();
}